#include <iostream>
#include <iterator>
#include <math.h>
#include "link.h"

using namespace std;

Link::Link(){
	this->p1 = NULL;
	this->p2 = NULL;
}
Link::Link(Point* pt1, Point* pt2){
	this->p1 = pt1;
	this->p2 = pt2;
}
Link::~Link(){
}
void Link::setP1(Point* p){
	this->p1 = p;
}
void Link::setP2(Point* p){
	this->p2 = p;
}
Point* Link::getP1(){
	return this->p1;
}
Point* Link::getP2(){
	return this->p2;
}
float Link::getWeight(Link* l){
	float weight = 0.0f;
	if(l != NULL){
		weight = Link::getWeight(l->getP1(),l->getP2());
	}
	return weight;
}

float Link::getWeight(Point* p1, Point* p2){
	float weight = 0.0f;
	int deltaX;
	int deltaY;
	if(p1 != NULL && p2 != NULL){
		deltaX = p1->getX() - p2->getX();
		deltaY = p1->getY() - p2->getY();
		weight = sqrt(deltaX*deltaX + deltaY*deltaY);
	}
	return weight; 
}
Point* Link::getIntersection(Link* l1, Link* l2){
	Point* p = NULL;
	//Verification si les liens existent
	if(l1 != NULL && l2 != NULL && l1 != l2){
		//Verification si les points des liens existent
		if(l1->getP1() != NULL && l1->getP2() != NULL && l2->getP1() != NULL && l2->getP2() != NULL){
			//Verification si pour chaque lien les points sont differents
			if((*(l1->getP1())) != (*(l1->getP2())) && (*(l2->getP1())) != (*(l2->getP2()))){
				//Calcule de l'equation des deux droites
				// sous la forme ax + by + c = 0
				float a1,c1,a2,c2;
				int b1,b2;
				if((l1->getP2()->getX()) != (l1->getP1()->getX())){
					//Cas d'une droite non verticale
					a1 = ((float)((l1->getP2()->getY())-(l1->getP1()->getY()))) / ((float)((l1->getP2()->getX())-(l1->getP1()->getX())));
					b1 = -1;
					c1 = l1->getP1()->getY() - a1 * l1->getP1()->getX();
				}
				else{
					//Cas d'une droit verticale
					a1 = -1;
					b1 = 0;
					c1 = l1->getP1()->getX();
				}
				if((l2->getP2()->getX()) != (l2->getP1()->getX())){
					//Cas d'une droite non verticale
					a2 = ((float)((l2->getP2()->getY())-(l2->getP1()->getY()))) / ((float)((l2->getP2()->getX())-(l2->getP1()->getX())));
					b2 = -1;
					c2 = l2->getP1()->getY() - a2 * l2->getP1()->getX();
				}
				else{
					//Cas d'une droit verticale
					a2 = -1;
					b2 = 0;
					c2 = l2->getP1()->getX();
				}
				//Si le deux droites ne sont pas paralleles
				if( a1*b2 != a2*b1 ){
					//Calcule des coordonnée du point d'intersection
					float x,y;
					float minX1,maxX1,minY1,maxY1;
					float minX2,maxX2,minY2,maxY2;
					x = (b1*c2 - b2*c1) / (a1*b2 - a2*b1);
					y = (a2*c1 - a1*c2) / (a1*b2 - a2*b1);

					minX1 = min(l1->getP1()->getX(),l1->getP2()->getX());
					maxX1 = max(l1->getP1()->getX(),l1->getP2()->getX());
					minY1 = min(l1->getP1()->getY(),l1->getP2()->getY());
					maxY1 = max(l1->getP1()->getY(),l1->getP2()->getY());

					minX2 = min(l2->getP1()->getX(),l2->getP2()->getX());
					maxX2 = max(l2->getP1()->getX(),l2->getP2()->getX());
					minY2 = min(l2->getP1()->getY(),l2->getP2()->getY());
					maxY2 = max(l2->getP1()->getY(),l2->getP2()->getY());
					//Verification si le point d'intersection est a l'interieur des deux liens (segments)
					if( (x >= minX1 && x <= maxX1 && x >= minX2 && x <= maxX2) && (y >= minY1 && y <= maxY1 && y >= minY2 && y <= maxY2) ){
                                                //Si c'est le cas alors on crée ce point pour le retourner
                                                p = new Point(x,y);
					}
				}
			}
		}
	}
	return p;
}
ostream & operator<<( ostream & out, Link l){
    out << "Lien entre " << (*l.getP1()) << " et " << (*l.getP2());
    return out;
}
